module General

import demo::common::Crawl;
import IO;
import util::Math;
import List;

import LinesOfCode;
import CyclomaticComplexity;
import UnitSize;
import Duplicates;
 
public list[loc] GetAllJavaFiles(str project)
{
	return crawl(|project://<project>/src|, ".java");
}

public void GetScore(str project)
{
	list[loc] files = GetAllJavaFiles(project);
	
	int linesOfCode = CountTotalLinesOfCode(files);
	str linesOfCodeScore = LinesOfCodeScore(linesOfCode);
	
	str cyclomaticComplexity = CyclomaticComplexityScore(files);
	
	str unitSize = GetUnitSizeScore(files);
	
	int duplicates = GetDuplicatesPercentage(files);
	str duplication = GetDuplicatesScore(duplicates);
	
	int volumeScore = weightResults(linesOfCodeScore), complexityScore = weightResults(cyclomaticComplexity), duplicationScore = weightResults(duplication), unitsizeScore = weightResults(unitSize);
 	str analisability = weightResultsBack(round(GiveMedian([volumeScore,duplicationScore,unitsizeScore]))), changeability = weightResultsBack(round(GiveMedian([complexityScore,duplicationScore]))), testability = weightResultsBack(round(GiveMedian([complexityScore,unitsizeScore])));
	
	println(" -----------------------");
	println("| PROJECT: <project> \t|");
	println(" -----------------------");
	println("| Lines Of Code \t|");
	println("| <linesOfCode> \t\t|");
	println("| Rank: " + linesOfCodeScore + " \t\t|");
	println(" -----------------------");
	println("| Cyclomatic Complexity |");
	println("| Rank: " + cyclomaticComplexity+ " \t\t|");
	println(" -----------------------");
	println("| Unitsize \t\t|");
	println("| Rank: " + unitSize+ " \t\t|");
	println(" -----------------------");
	println("| Duplications \t\t|");
	println("| Rank: " + duplication+ " \t\t|");
	println("| Analysability: " + analisability + "\t|");
	println("| Changeability: " + changeability + "\t|");
	println("| Testability: " + testability + " \t|");
	println(" -----------------------");
}

private int weightResults(str score)
{
	int result = 0;
	switch(score){
		case "++": result = 2;
		case "+": result = 1;
		case "o": result = 0;
		case "-": result = -1;
		case "--": result = -2;
} 
	return result;
}

private str weightResultsBack(int score)
{
	str result = "";
	switch(score){
		case 2: result = "++";
		case 1: result = "+";
		case 0: result = "o";
		case -1: result = "-";
		case -2: result = "--";
	} 
	
	return result;
}

public num GiveMedian(list[num] values)
{
	return (sum(values)/size(values));
}